package com.yonyou.cyxdms.basedata.service.service.code;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yonyou.cyx.framework.compent.redis.RedisClient;
import com.yonyou.cyx.framework.util.bean.ApplicationContextHelper;
import com.yonyou.cyx.function.exception.DALException;
import com.yonyou.cyx.function.exception.ServiceBizException;
import com.yonyou.cyx.function.utils.bean.BeanMapperUtil;
import com.yonyou.cyx.function.utils.common.StringUtils;
import com.yonyou.cyx.function.utils.jsonserializer.JSONUtil;
import com.yonyou.cyxdms.basedata.client.constants.BaseDataCommonConstants;
import com.yonyou.cyxdms.basedata.client.constants.BaseDataDictConstants;
import com.yonyou.cyxdms.basedata.client.domains.vo.CodeVO;
import com.yonyou.cyxdms.basedata.client.domains.vo.DictVO;
import com.yonyou.cyxdms.basedata.client.dto.code.CodeDTO;
import com.yonyou.cyxdms.basedata.client.dto.code.SearchCodeDTO;
import com.yonyou.cyxdms.basedata.service.constant.BasedataDictConstants;
import com.yonyou.cyxdms.basedata.service.entity.code.CodePO;
import com.yonyou.cyxdms.basedata.service.repository.code.CodeMapper;
import com.yonyou.cyxdms.framework.bean.dto.user_info.LoginInfoDto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 系统固定代码 服务实现类
 * </p>
 *
 * @author renwd
 * @since 2018-12-12
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class CodeServiceImpl extends ServiceImpl<CodeMapper, CodePO> implements CodeService {

    private final Logger logger = LoggerFactory.getLogger(CodeServiceImpl.class);

    @Autowired
    CodeMapper codeMapper;

    @Autowired
    private RedisClient redisClient;

    @Override
    public List getTcCodeByType(Map<String, Object> queryParam) {
        return codeMapper.queryTcCodeListByType(queryParam);
    }

    /**
     * 本接口忽略登录所以传appId(因为有的excel导出用到了)
     *
     * @param appId
     * @return java.util.List<com.yonyou.cyxdms.basedata.client.domains.vo.CodeVO>
     * @author renwd
     * @since 2019/10/16
     */
    @Override
    public List<CodeVO> getTcCode(String appId){
        logger.info("getTcCode:appId:{}", appId);
        if(StringUtils.isNullOrEmpty(appId)){
            appId = "cyx";
        }
        return codeMapper.queryTcCodeList(appId);
    }

    /**
     * 根据codeName查询codeId
     *
     * @author ysj
     * @date 2019/10/21
     * @param codeName
     * @return
     */
    @Override
    public CodeVO getTcCodeByName(String codeName,Integer type) {
        LoginInfoDto loginInfoDto = ApplicationContextHelper.getBeanByType(LoginInfoDto.class);
        LambdaQueryWrapper<CodePO> query = new QueryWrapper<CodePO>().lambda();
        query.eq(CodePO::getCodeCnDesc,codeName);
        query.eq(CodePO::getAppId,loginInfoDto.getAppId());
        query.eq(CodePO::getType, type);

        List<CodePO> codes = codeMapper.selectList(query);
        if(codes.size()==1){
            return BeanMapperUtil.copyProperties(codes.get(0),CodeVO.class);
        }
        return null;
    }

    /**
     * 根据appId查询所有tc_code(pc登录)
     *
     * @return java.util.List<com.yonyou.cyxdms.basedata.service.vo.DictVO>
     * @author renwd
     * @since 2019/10/16
     */
    @Override
    public List<DictVO> allCode() {
        LoginInfoDto loginInfoDto = ApplicationContextHelper.getBeanByType(LoginInfoDto.class);
        String appId = loginInfoDto.getAppId();
        String messageFormat = MessageFormat.format(BaseDataCommonConstants.ALLCODE_CACHE_TYPE, appId);
        Object codeData = redisClient.get(messageFormat);
        if (null == codeData) {
            LambdaQueryWrapper<CodePO> codeParam = new QueryWrapper<CodePO>().lambda();
            codeParam.eq(CodePO::getAppId, appId).eq(CodePO::getIsDeleted, 0).orderByAsc(CodePO::getType,CodePO::getNum);
            List<CodePO> codeList = codeMapper.selectList(codeParam);

            List<DictVO> dictVOList = BeanMapperUtil.copyList(codeList, DictVO.class);
            redisClient.set(messageFormat, JSONUtil.objectToJson(dictVOList), BaseDataCommonConstants.EXPIRE_TIME_ONE_DAY);
            return dictVOList;
        }
        return JSONUtil.jsonToList(JSONUtil.objectToJson(codeData), DictVO.class);
    }

    /**
     * 根据appId查询全部可用字典
     *
     * @author lyz
     * @date 2021/3/8
     */
    @Override
    public List<DictVO> allCodeAvailable() {
        LoginInfoDto loginInfoDto = ApplicationContextHelper.getBeanByType(LoginInfoDto.class);
        String appId = loginInfoDto.getAppId();
        String messageFormat = MessageFormat.format(BaseDataCommonConstants.ALLCODE_AVAI_CACHE_TYPE, appId);
        Object codeData = redisClient.get(messageFormat);
        if (null == codeData) {
            LambdaQueryWrapper<CodePO> codeParam = new QueryWrapper<CodePO>().lambda();
            codeParam.eq(CodePO::getAppId, appId).eq(CodePO::getIsDeleted, 0)
                    .eq(CodePO::getStatus, BaseDataDictConstants.IS_ON)
                    .orderByAsc(CodePO::getType, CodePO::getNum);
            List<CodePO> codeList = codeMapper.selectList(codeParam);

            List<DictVO> dictVOList = BeanMapperUtil.copyList(codeList, DictVO.class);
            redisClient.set(messageFormat, JSONUtil.objectToJson(dictVOList), BaseDataCommonConstants.EXPIRE_TIME_ONE_DAY);
            return dictVOList;
        }
        return JSONUtil.jsonToList(JSONUtil.objectToJson(codeData), DictVO.class);
    }

    /**
     * 根据type查询code
     *
     * @param type type
     * @return java.util.List<com.yonyou.cyx.base.bean.entity.CodePO>
     * @author renwd
     * @since 2018/11/22
     */
    @Override
    public List<CodeVO> queryCode(String type) {
        logger.debug("FeignType：{}", type);
        LambdaQueryWrapper<CodePO> queryWrapper = new QueryWrapper<CodePO>().lambda();
        queryWrapper.eq(CodePO::getType, Integer.valueOf(type));
        List<CodePO> codeList = codeMapper.selectList(queryWrapper);
        return BeanMapperUtil.copyList(codeList, CodeVO.class);
    }

    /**
     * 根据查询条件返回结果集
     *
     * @param id 主键ID
     * @return java.util.List<java.util.Map < java.lang.String , java.lang.Object>>
     * @author chengliang
     * @since 2018/7/22 0022
     */
    @Override
    @Transactional(readOnly = true)
    public Map<String, Object> getById(Integer id) {
        CodePO codePo = codeMapper.selectById(id);
        if(codePo!=null){
            return codePo.toMaps();
        }else{
            throw new DALException("查询失败,没有符合条件的数据");
        }
    }

    /**
     * 根据DTO 进行数据新增
     *
     * @param codeDto 页面DTO
     * @return void
     * @author chengliang
     * @since 2018/7/21 0021
     */
    @Override
    public Map<String,Object> insertCodePo(CodeDTO codeDto) {
        LoginInfoDto loginInfoDto = ApplicationContextHelper.getBeanByType(LoginInfoDto.class);
        //对对象进行赋值操作
        CodePO codePo = BeanMapperUtil.copyProperties(codeDto,CodePO.class);
        // 插入主键
        codePo.setCodeId(this.getNextCodeId(BasedataDictConstants.TYPE,loginInfoDto));
        codePo.setNum(this.getNextNum(BasedataDictConstants.TYPE,loginInfoDto));
        codePo.setAppId(loginInfoDto.getAppId());
        codeMapper.insert(codePo);
        //返回插入的值
        return codePo.toMaps();
    }

    /**
     * 获取下一个code的id(因为没有主键)
     *
     * @param type
     * @param loginInfoDto
     * @return java.lang.Integer
     * @author renwd
     * @since 2019/10/16
     */
    @Override
    public Integer getNextCodeId(Integer type,LoginInfoDto loginInfoDto) {
        return codeMapper.getNextCodeId(type,loginInfoDto.getAppId());
    }

    /**
     * 获取下一个code的num
     *
     * @param type
     * @param loginInfoDto
     * @return java.lang.Integer
     * @author renwd
     * @since 2019/10/16
     */
    @Override
    public Integer getNextNum(Integer type,LoginInfoDto loginInfoDto) {
        return codeMapper.getNextNum(type,loginInfoDto.getAppId());
    }


    /**
     * 修改tc_code
     *
     * @param codeDto
     * @return java.util.Map<java.lang.String,java.lang.Object>
     * @author chengliang
     * @since 2019/10/16
     */
    @Override
    public Map<String, Object> updateCodePo(CodeDTO codeDto) {
        LoginInfoDto loginInfoDto = ApplicationContextHelper.getBeanByType(LoginInfoDto.class);
        //查询条件
        LambdaQueryWrapper<CodePO> queryWrapper = new QueryWrapper<CodePO>().lambda();
        queryWrapper.eq(CodePO::getCodeId,codeDto.getCodeId());
        queryWrapper.eq(CodePO::getAppId,loginInfoDto.getAppId());
        CodePO codePo = codeMapper.selectOne(queryWrapper);
        BeanMapperUtil.copyProperties(codeDto,codePo);
        //先删除再添加--update方法不好使
        codeMapper.delete(queryWrapper);
        codeMapper.insert(codePo);
        return codePo.toMaps();
    }

    @Override
    public Integer deleteByCodeId(Integer codeId){
        int del = codeMapper.delete(new LambdaQueryWrapper<CodePO>()
                .eq(CodePO::getCodeId, codeId));
        return del;
    }

    /**
     * ID查CODE
     *
     * @param:
     * @return:
     * @auther: tanjie
     * @since: 2019/10/16
     */
    @Override
    public CodeVO queryById(Long id) {
        LambdaQueryWrapper<CodePO> query = new QueryWrapper<CodePO>().lambda().eq(CodePO::getCodeId, id);
        List<CodePO> codes = codeMapper.selectList(query);
        return null == codes ? null : BeanMapperUtil.copyProperties(codes.get(0), CodeVO.class);
    }

    /**
     * 根据codeId查询
     *
     * @param codeId
     * @param appId
     * @return com.yonyou.cyxdms.basedata.client.domains.vo.CodeVO
     * @author dengqiang
     * @since 2019/11/1
     */
    @Override
    public CodeVO queryByCodeId(Long codeId, String appId) {
        return codeMapper.queryByCodeId(codeId,appId);
    }


    /**
     * 分页查询字典项
     *
     * @author zhangjinyin
     * @since 2020/11/26
     */
    @Override
    public List<CodeDTO> queryList(Page page, SearchCodeDTO dto) {
        LoginInfoDto loginInfoDto = ApplicationContextHelper.getBeanByType(LoginInfoDto.class);
        List<CodeDTO> list = codeMapper.queryList(page,dto,loginInfoDto);
        CodeConverter codeConverter = CodeConverter.M;
        return codeConverter.toDtoList(list);
    }

    /**
     * 获取全部类型
     *

     * @author zhangjinyin
     * @since 2020/11/26
     */
    @Override
    public List<CodeDTO> getAllCodeType(String typeName) {
        LoginInfoDto loginInfoDto = ApplicationContextHelper.getBeanByType(LoginInfoDto.class);
        return codeMapper.getAllCodeType(typeName,loginInfoDto);
    }

    /**
     * 根据id 获取 字典项
     *
     * @param codeId
     * @author zhangjinyin
     * @since 2020/11/26
     */
    @Override
    public CodeDTO getCodeById(Integer codeId) {
        LoginInfoDto loginInfoDto = ApplicationContextHelper.getBeanByType(LoginInfoDto.class);
        return codeMapper.getCodeById(codeId,loginInfoDto);
    }

    /**
     * 新增修改字典项
     *
     * @author zhangjinyin
     * @since 2020/11/26
     */
    @Override
    public Boolean saveCode(CodeDTO codeDTO) {
        LoginInfoDto loginInfoDto = ApplicationContextHelper.getBeanByType(LoginInfoDto.class);
        String typeName = codeMapper.getTypeNameByType(codeDTO.getType(),loginInfoDto);
        if(codeDTO.getType() == null || org.apache.commons.lang3.StringUtils.isBlank(codeDTO.getTypeName())){
            throw new ServiceBizException("请选择类型！");
        }
        if(!codeDTO.getTypeName().equals(typeName)){
            throw new ServiceBizException("代码类型与类型名称不相符，无法保存！");
        }
        if(codeDTO.getCodeId() == null){
            codeDTO.setCodeId(codeMapper.getNextCodeId(codeDTO.getType(),loginInfoDto.getAppId()));
            codeDTO.setNum(codeMapper.getNextNum(codeDTO.getType(),loginInfoDto.getAppId()));
            codeMapper.insertCode(codeDTO,loginInfoDto);
        }else {
            codeMapper.upadteCode(codeDTO,loginInfoDto);
        }
        /* 清除redis缓存 **/
        String appId = loginInfoDto.getAppId();
        String messageFormat = MessageFormat.format(BaseDataCommonConstants.ALLCODE_AVAI_CACHE_TYPE, appId);
        redisClient.del(messageFormat);
        return true;
    }

    @Override
    public void refreshCode(String appId) {
        String messageFormat = MessageFormat.format(BaseDataCommonConstants.ALLCODE_AVAI_CACHE_TYPE, appId);
        LambdaQueryWrapper<CodePO> codeParam = new QueryWrapper<CodePO>().lambda();
        codeParam.eq(CodePO::getAppId, appId).eq(CodePO::getIsDeleted, 0)
                .eq(CodePO::getStatus, BaseDataDictConstants.IS_ON)
                .orderByAsc(CodePO::getType, CodePO::getNum);
        List<CodePO> codeList = codeMapper.selectList(codeParam);

        List<DictVO> dictVOList = BeanMapperUtil.copyList(codeList, DictVO.class);
        redisClient.set(messageFormat, JSONUtil.objectToJson(dictVOList), BaseDataCommonConstants.EXPIRE_TIME_ONE_DAY);
    }
}
